﻿namespace System.Threading
{
    public sealed class ReaderWriterLockSlim
    {
        private readonly ManualResetEvent activeWriter = new ManualResetEvent(false);
        private int activeReaders;

        public bool TryEnterReadLock(int millisecondsTimeout)
        {
#if PORTABLE
            if (!Monitor.TryEnter(activeWriter))
#else
            if (!Monitor.TryEnter(activeWriter, millisecondsTimeout))
#endif
            return false;
            Interlocked.Increment(ref activeReaders);
            Monitor.Exit(activeWriter);
            return true;
        }

        public void ExitReadLock()
        {
            if (Interlocked.Decrement(ref activeReaders) == 0) activeWriter.Set();
        }

        public bool TryEnterWriteLock(int millisecondsTimeout)
        {
#if PORTABLE
            if (!Monitor.TryEnter(activeWriter))
#else
            if (!Monitor.TryEnter(activeWriter, millisecondsTimeout))
#endif
                return false;
            activeWriter.Reset();
            if (activeReaders > 0) activeWriter.WaitOne();
            activeWriter.Reset();
            return true;
        }

        public void ExitWriteLock()
        {
            Monitor.Exit(activeWriter);
        }
    }
}